//#ifndef __WEBSOCKET_UTIL_H_H__
#define __WEBSOCKET_UTIL_H_H__
#include <string>
#include <vector>
#include <map>
#include "../Core/Buffer.h"
using net::Buffer;
class WebSocketUtil
{
public:
	// 4 bits
	enum OPCODE : unsigned char
	{
		CONTINUATION_FRAME = 0x0,
		TEXT_FRAME = 0x1,
		BINARY_FRAME = 0x2,
		RESERVED1 = 0x3,
		RESERVED2 = 0x4,
		RESERVED3 = 0x5,
		RESERVED4 = 0x6,
		RESERVED5 = 0x7,
		CLOSE = 0x8,
		PING = 0x9,
		PONG = 0xA,
		RESERVED6 = 0xB,
		RESERVED7 = 0xC,
		RESERVED8 = 0xD,
		RESERVED9 = 0xE,
		RESERVED10 = 0xF
	};

	enum HEADER : unsigned int
	{
		// in byte
		FLAG_LEN = 2,
		EXT_PAYLOAD_LEN_1 = 2,
		EXT_PAYLOAD_LEN_2 = 6,
		MASK_KEY_LEN = 4,
		MAX_HEADER_LEN = FLAG_LEN + EXT_PAYLOAD_LEN_1 + EXT_PAYLOAD_LEN_2 + MASK_KEY_LEN,
	};

	struct Header {
		char data[HEADER::MAX_HEADER_LEN] = { 0 };
		int len = 0;
	};

	typedef std::map<std::string, std::string> HttpHeaderMap;
public:
	WebSocketUtil() = delete;
	~WebSocketUtil() = delete;
	WebSocketUtil(const WebSocketUtil& other) = delete;
	WebSocketUtil(const WebSocketUtil&& other) = delete;
public:
	static bool HandShake(const std::string& data, Buffer *outbuf, HttpHeaderMap& outHttpHeader, bool &isCompressed, std::string& outResponse);
	static bool Decode(Buffer *inbuf, std::string& outdata, bool& fin, unsigned char& opcode, bool isCompressed);
	static bool Encode(const std::string& data, Buffer *outbuf, bool fin, unsigned char opcode, const char *maskKey, bool isCompressed);
	static bool GetPing(Buffer *outbuf, const char *maskKey, bool isCompressed);
	static bool GetPong(Buffer *outbuf, const char *maskKey, bool isCompressed);
private:
	static void Mask(std::string& data, const char *key);
	static bool parseHttpPath(const std::string& str, std::string& outurl, std::string& outparams);
	static void makeUpgradeResponse(const char* secWebSocketAccept, bool isCompressed, std::string& response);
};

//#endif  // !__WEBSOCKET_UTIL_H_H__
